package eval.host;

import java.util.List;
import java.util.Map;
import eval.deploy.IDemandManager;
import eval.exceptions.CpuLeakAtHostException;
import eval.exceptions.MemLeakAtHostException;
import eval.vm.VirtualMachine;

/**
 * Interface for the main operations offered by the host manager
 * 
 * @author Nicolo' M. Calcavecchia <calcavecchia@elet.polimi.it>
 * @author Amit Peled   <amit.kapina@gmail.com>
 * @author Igal Kaufman <igal.kaufman@gmail.com> 
 */
public interface IHostManager {

	/**
	 * Adds the given host to the list of known hosts by the host manager.
	 * 
	 * @param host to add
	 */
	public void addHost(Host host);

	/**
	 * Add List of Hosts to the list of known hosts by the host manager.
	 * 
	 * @param hosts the list
	 */
	public void addHosts(List<Host> hosts);

	/**
	 * Returns the total number of hosts in the cloud infrastructure.
	 * 
	 * @return total number of hosts
	 */
	public int getNumberOfHosts();

	/**
	 * Returns the list of all generated hosts
	 * 
	 * @return list of Hosts
	 */
	public List<Host> getHosts();

	/**
	 * Returns the CPU capacity for the given host number.
	 * The host number starts from 0
	 * 
	 * @param host 
	 * @return CPU capacity
	 */
	public int getCpuCapacityForHost(Host host);

	/**
	 * Returns the MEM capacity for the given host number.
	 * The host number starts from 0
	 * 
	 * @param host
	 * @return MEM capacity
	 */
	public int getMemCapacityForHost(Host host);

	/**
	 * Prints into the console all hosts in the system
	 * 
	 */
	public void printAllHosts();

	/**
	 * Returns the total CPU capacity of hosts available in the data center
	 * 
	 * @return total CPU
	 */
	public int getTotalCpuCapacity();

	/**
	 * Returns the total MEM capacity of hosts available in the data center
	 * 
	 * @return total MEM
	 */
	public int getTotalMemCapacity();

	/**
	 * Returns a Map associating at each king of host the percentage of that
	 * type of hosts
	 * 
	 * @return map 
	 */
	public Map<HostCapacityEnum, Double> getHostDistribution();


	/**
	 * Get CPU Capacity of host type 
	 * 
	 * @param hostType
	 * @return CPU Capacity
	 */
	public int getCpuCapacityOfType(HostCapacityEnum hostType);

	/**
	 * Get MEM Capacity of host type 
	 * 
	 * @param hostType
	 * @return MEM Capacity
	 */
	public int getMemCapacityOfType(HostCapacityEnum hostType);

	/**
	 * Get the HostCapacity
	 * 
	 * @param hostType
	 * @return HostCapacity
	 */
	public HostCapacity getHostCapacity(HostCapacityEnum hostType);

	/**
	 * open new host at tick
	 * @param tick
	 * @return the new open host, null if no host opened
	 */
	public Host openNewHost(int tick);

	/**
	 * update demand on host
	 * 
	 * @param demandManager
	 * @param host the host to update
	 * @param vmsInHost VMs on the host
	 * @param tick
	 */
	public void updateCurrentHostDemand(IDemandManager demandManager,Host host , List<VirtualMachine> vmsInHost, int tick);

	/**
	 * set the 3 list of HostManager.
	 * 
	 */
	public void InitHostsInCloud();

	/**
	 * 
	 * @return list of all the open hosts and the candidates for closing as well.
	 */
	public List<Host> getOpenHosts();

	/**
	 * Get number of open hosts
	 * 
	 * @return the number of open and candidate for closing hosts.
	 */
	public int getNumberOfOpenHosts();

	/**
	 * Get number of closed hosts
	 * 
	 * @return the number of closed host in the cloud.
	 */
	public int getNumberOfClosedHosts();

	/**
	 * Get host by id
	 * 
	 * @param hostIdentifier host id
	 * @return the host from the hosts list with the given host ID. 
	 */
	public Host getHostByID(int hostIdentifier);

	/**
	 * 
	 * @return the total amount of CPU units which in use in the cloud.
	 */
	public int getToatalCpuLoadOnCloud();

	/**
	 * open host with at least neededCPU 
	 * if no Host found, open the biggest Host
	 * 
	 * @param neededCPU the minimum, CPU require
	 * @param tick
	 * @return true if succeeded.
	 */
	public boolean openNewHostWithMinCpu(double neededCPU,int tick);

	/**
	 * this function close the given host.
	 * 
	 * @param host
	 */
	public void closeHost(Host host);

	/**
	 * this function declare the given host as candidate for closing.
	 * 
	 * @param host
	 * @param tickRemainingForClosing
	 */
	public void makeHostCandidateForClosing(Host host,int tickRemainingForClosing);

	/**
	 * this function declare the given host as open and not candidate for closing. 
	 * 
	 * @param host
	 */
	public void removeHostFromCandidateForClosing(Host host );

	/**
	 * set the current CPU and MEM units which in use on the given host.
	 * 
	 * @param host
	 * @param cpuLoad
	 * @param memLoad
	 */
	public void setHostCurrentLoad(Host host,int cpuLoad, int memLoad);

	/**
	 * set the current CPU units which in use on the given host
	 * 
	 * @param host
	 * @param cpuLoad
	 * @throws Exception
	 */
	public void setHostCurrentCpuLoad(Host host,int cpuLoad) throws Exception;

	/**
	 * set the current MEMORY units which in use on the given host
	 * 
	 * @param host
	 * @param memLoad
	 * @throws Exception
	 */
	public void setHostCurrentMemLoad(Host host,int memLoad) throws Exception;

	/**
	 * this function calls updateHostCurrentCpuLoad and  updateHostCurrentMemLoad
	 * 
	 * @param host
	 * @param cpuLoad
	 * @param memLoad
	 */
	public void updateHostCurrentLoad(Host host,int cpuLoad,int memLoad);

	/**
	 * this function add the cpuLoad parameter to the current CPU 
	 * load on the given host.
	 * 
	 * @param host
	 * @param cpuLoad
	 * @throws CpuLeakAtHostException
	 */
	public void updateHostCurrentCpuLoad(Host host,int cpuLoad) throws CpuLeakAtHostException;

	/**
	 * this function add the memLoad parameter to the current MEMORY
	 *  load on the given host.
	 *  
	 * @param host
	 * @param memLoad
	 * @throws MemLeakAtHostException
	 */
	public void updateHostCurrentMemLoad(Host host,int memLoad) throws MemLeakAtHostException;

	/**
	 * delete the given VM's list from the cloud.
	 * 
	 * @param removeList
	 */
	public void removeListOfVmFromHosts(List<VirtualMachine> removeList);

	/**
	 * add the given VM to the given host.
	 * 
	 * @param host
	 * @param vm
	 * @param cpuLoad
	 * @param memLoad
	 */
	public void addVmToHost(Host host,VirtualMachine vm, int cpuLoad, int memLoad);

	/**
	 * Get VMs that deploy on host
	 * 
	 * @param host
	 * @return the VM's currently located in the host.
	 */
	public List<VirtualMachine> getVmsAtHost (Host host);

	/**
	 * Get CPU free at host 
	 * 
	 * @param host
	 * @return the free CPU space in the host.
	 */
	public int getCpuAvailableAtHost(Host host);

	/**
	 * 
	 * @param hostCapacityEnum
	 * @return the cost to open new host based on the host type.
	 */
	public double getStartUpCostForHost(HostCapacityEnum hostCapacityEnum);

	/**
	 * 
	 * @param load
	 * @return the cost of the currently CPU used in the host.(i.e. load * load cost).
	 */
	public double getLoadCost(int load);

	/**
	 * 
	 * @param totalCloudCPULoad
	 * @return the profit from the CPU currently used in the host, (i.e. load * income on load).
	 */
	public double getIncomeOnLoad(int totalCloudCPULoad);

	/**
	 * 
	 * @return the total Memory units currently used in the cloud. 
	 */
	public int getToatalMemLoadOnCloud();

	/**
	 * @param hostCapacityEnum
	 * @return the cost of the host when it's empty based on the host type.
	 */
	public double getBaseCostForHost(HostCapacityEnum hostCapacityEnum);

	/**
	 * open the given host.
	 * 
	 * @param host
	 * @param tick
	 */
	public void openHost(Host host, int tick);

	/**
	 * move the given VM from one host to another.
	 * 
	 * @param vm
	 * @param fromHost
	 * @param toHost
	 * @param cpu
	 * @param mem
	 */
	public void relocateVm(VirtualMachine vm, Host fromHost, Host toHost, int cpu, int mem);

	/**
	 * 
	 * @return all the VM's which placed in all the open hosts.
	 */
	public List<VirtualMachine> getAllVmAtOpenHosts();

	/**
	 * remove the given VM from the cloud.
	 * 
	 * @param vm
	 */
	public void rejectVms(VirtualMachine vm);

}
